package com.caiyi.financial.nirvana.sms.util;

import com.alibaba.fastjson.JSON;
import com.caiyi.financial.nirvana.sms.cache.BlackMobileCache;
import com.caiyi.financial.nirvana.sms.cache.SmsMateCache;
import com.caiyi.financial.nirvana.sms.entity.SmsGateway;
import com.caiyi.financial.nirvana.sms.entity.SmsProduct;
import com.caiyi.financial.nirvana.sms.entity.SmsUser;
import com.caiyi.financial.nirvana.sms.enums.*;
import com.caiyi.financial.nirvana.sms.jedis.JedisKey;
import com.caiyi.financial.nirvana.sms.jedis.JedisService;
import com.caiyi.financial.nirvana.sms.queue.SendQueueEntity;
import com.youyu.common.exception.BizException;
import com.youyu.common.utils.YyAssert;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 短信发送
 */
public class CoreSendUtil {

    private static final Logger logger = LoggerFactory.getLogger(CommUtil.class);

    public static void handlerBusiness(Set<String> phones, SendQueueEntity entity, SmsUser smsUser) {
        String proJson = JedisService.get(String.format(JedisKey.SMS_PRODUCT, smsUser.getProductId()));
        SmsProduct product = JSON.parseObject(proJson, SmsProduct.class);
        YyAssert.isFalse(StringUtils.isBlank(product.getYdGateways()) || StringUtils.isBlank(product.getLtGateways()) || StringUtils.isBlank(product.getDxGateways()), ReturnCodeEnum.GATEWAY_CONFIG_ERROR);
        String[] ydGateWayIds = product.getYdGateways().split(",");
        String[] ltGateWayIds = product.getLtGateways().split(",");
        String[] dxGateWayIds = product.getDxGateways().split(",");
        YyAssert.isFalse(ydGateWayIds == null || ltGateWayIds == null || dxGateWayIds == null, ReturnCodeEnum.GATEWAY_CONFIG_ERROR);
        Map<String, SmsGateway> gateWayMaps = getGateWayMaps(ydGateWayIds, ltGateWayIds, dxGateWayIds);
        Integer type = smsUser.getType();
        YyAssert.isFalse(type == null, ReturnCodeEnum.ACCOUNT_TYPE_ERROR);
        //行业短信发送
        if (type == SmsUserTypeEnum.INDUSTRY.index) {
            handlerIndustry(phones, entity, smsUser, gateWayMaps, ydGateWayIds, ltGateWayIds, dxGateWayIds);
        }
        //营销短信发送
        else {
            handlerMarket(phones, entity, smsUser, ydGateWayIds[0], ltGateWayIds[0], dxGateWayIds[0], gateWayMaps);
        }
    }

    private static void handlerMarket(Set<String> phones, SendQueueEntity entity, SmsUser smsUser, String ydGateWayId, String ltGateWayId, String dxGateWayId, Map<String, SmsGateway> gateWayMaps) {
//        entity.setNotifyUrl(null);//营销不允许设置回调地址
        Integer msgCount = phones.size() * CommUtil.splitLongContent(entity.getContent()).size();
        //其中有一个网关被禁用情况
        if (gateWayMaps.get(ydGateWayId) == null || gateWayMaps.get(ltGateWayId) == null || gateWayMaps.get(dxGateWayId) == null) {
            //返还余额
            String key = String.format(JedisKey.SMS_BALANCE, entity.getAccount());
            JedisService.incrBy(key, msgCount);
            JedisService.lpush(JedisKey.SMS_QUEUE_BALANCE_UPDATE, smsUser.getId() + "=" + (msgCount));
            logger.error("CoreSendUtil gateWayMaps has null !!! ");
            throw new BizException(ReturnCodeEnum.GATEWAY_CONFIG_ERROR.code, ReturnCodeEnum.GATEWAY_CONFIG_ERROR.desc);
        }
        Set<String> ydPhones = new HashSet<>(), ltPhones = new HashSet<>(), dxPhones = new HashSet<>();

        for (String phone : phones) {
            int operator = CommUtil.getPhoneOperator(phone);
            if (operator == SmsMsgOperatorEnum.YD.index) {
                ydPhones.add(phone);
                continue;
            }
            if (operator == SmsMsgOperatorEnum.LT.index) {
                ltPhones.add(phone);
                continue;
            }
            if (operator == SmsMsgOperatorEnum.DX.index) {
                dxPhones.add(phone);
                continue;
            }
        }
        String ydId = ydGateWayId, ltId = ltGateWayId, dxId = dxGateWayId;
        if (ltId.equals(dxId)) {
            ltPhones.addAll(dxPhones);
            dxPhones.clear();
        }
        if (ydId.equals(ltId)) {
            ydPhones.addAll(ltPhones);
            ltPhones.clear();
        }
        if (ydId.equals(dxId)) {
            ydPhones.addAll(dxPhones);
            dxPhones.clear();
        }
//        int ydCode = decide(gateWayMaps.get(ydId).getCustom(), ydPhones.size());
//        int ltCode = decide(gateWayMaps.get(ltId).getCustom(), ltPhones.size());
//        int dxCode = decide(gateWayMaps.get(dxId).getCustom(), dxPhones.size());
        //号码小于最小值
//        if (ydCode == -1 || ltCode == -1 || dxCode == -1) {
//            String desc = ydCode == -1 ? "移动" : ltCode == -1 ? "联通" : dxCode == -1 ? "电信" : "";
//            logger.info("号码小于最小值 phone size is yd {},lt {},dx {}", ydPhones.size(), ltPhones.size(), dxPhones.size());
//            //返还余额
//            String key = String.format(JedisKey.SMS_BALANCE, entity.getAccount());
//            JedisService.incrBy(key, msgCount);
//            JedisService.lpush(JedisKey.SMS_QUEUE_BALANCE_UPDATE, smsUser.getId() + "=" + (msgCount));
//            throw new BizException(ReturnCodeEnum.PHONE_SIZE_ERROR.code, String.format(ReturnCodeEnum.PHONE_SIZE_ERROR.desc, desc));
//        }
        //batch表入库队列
        JedisService.lpush(JedisKey.SMS_QUEUE_BATCH_MSG_DB, JSON.toJSONString(entity));
        if (ydPhones.size() > 0) {
            handlerSimpleMarket(ydPhones, entity, smsUser, gateWayMaps, ydGateWayId);
        }
        if (ltPhones.size() > 0) {
            handlerSimpleMarket(ltPhones, entity, smsUser, gateWayMaps, ltGateWayId);
        }
        if (dxPhones.size() > 0) {
            handlerSimpleMarket(dxPhones, entity, smsUser, gateWayMaps, dxGateWayId);
        }
    }

//    public static void handlerBatchMarket(Set<String> phones, SendQueueEntity entity, SmsUser user, Map<String, SmsGateway> gateWayMaps, String gatewayId) {
////        if (code == 0) {
//            handlerSimpleMarket(phones, entity, user, gateWayMaps, gatewayId);
////        } else {
////            int batch = phones.size() / code;
////            if (phones.size() % code != 0) {
////                batch++;
////            }
////            List<String> list = new ArrayList<>(phones);
////            for (int i = 0; i < batch; i++) {
////                int endIndex = (i + 1) * code;
////                if (endIndex > phones.size()) {
////                    endIndex = phones.size();
////                }
////                List<String> batchList = list.subList(i * code, endIndex);
////                handlerSimpleMarket(batchList, entity, user, gateWayMaps, gatewayId);
////            }
////        }
//    }

    /**
     * 处理行业短信
     */
    public static void handlerIndustry(Set<String> phones, SendQueueEntity entity, SmsUser user, Map<String, SmsGateway> gateWayMaps, String[] ydGateWayIds, String[] ltGateWayIds, String[] dxGateWayIds) {
        //batch表入库队列
        JedisService.lpush(JedisKey.SMS_QUEUE_BATCH_MSG_DB, JSON.toJSONString(entity));
        for (String phone : phones) {
            String[] mate = SmsMateCache.mate(phone);
            if (mate != null) {
                entity.setProvince(mate[0]);
                entity.setCity(mate[1]);
            }
            entity.setMessageId(CommUtil.generateMessageId());
            entity.setPhone(phone);
            int operator = CommUtil.getPhoneOperator(phone);
            entity.setOperator(operator);
            entity.setAction(MessageActionEnum.INSERT.index);
            entity.setNum(CommUtil.splitLongContent(entity.getContent()).size());
            entity.setGatewayId(0);
            entity.setAccessNumber("0");
            entity.setSendTime(new Date());
            entity.setStatus(SmsMsgStatusEnum.REQUEST_FAIL.index);
            //黑名单处理
            if (BlackMobileCache.checkMobile(phone)) {
                entity.setResult("MBBLACK-S");
                String msgJson = JSON.toJSONString(entity);
                JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, msgJson);
                continue;
            }
            //获取白名单
            String whiteListKey = String.format(JedisKey.SMS_WHITE_LIST_ACCOUNT, entity.getAccount());
            if (!JedisService.sismember(whiteListKey, phone)) {
                if (BlackMobileCache.checkMobile(entity.getAccount(), phone)) {
                    entity.setResult("MBBLACK-A");
                    String msgJson = JSON.toJSONString(entity);
                    JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, msgJson);
                    continue;
                }
                //处理短信发送频率
                if (!DisturbUtil.isDisturbed(user, phone)) {
                    entity.setResult("短信发送过于频繁");
                    String msgJson = JSON.toJSONString(entity);
                    JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, msgJson);
                    continue;
                }
            }
            String gatewayId = getGatewayId(operator, ydGateWayIds, ltGateWayIds, dxGateWayIds, entity);

            int flag = 0;
            while (gateWayMaps.get(gatewayId) == null && flag < 3) {
                gatewayId = getGatewayId(operator, ydGateWayIds, ltGateWayIds, dxGateWayIds, entity);
                flag++;
            }
            //通道为纯验证码类型
            if (gateWayMaps.get(gatewayId) != null) {
                if (gateWayMaps.get(gatewayId).getGatewayType() == SmsUserTypeEnum.CAPTCHA.index && CommUtil.needFree(entity.getContent())) {
                    while ((gateWayMaps.get(gatewayId) == null || gateWayMaps.get(gatewayId).getGatewayType() == SmsUserTypeEnum.CAPTCHA.index) && flag < 3) {
                        gatewayId = getGatewayId(operator, ydGateWayIds, ltGateWayIds, dxGateWayIds, entity);
                        flag++;
                    }
                }
            }
            if (gateWayMaps.get(gatewayId) == null) {
                entity.setResult("通道配置错误");
                String msgJson = JSON.toJSONString(entity);
                JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, msgJson);
                continue;
            }
            entity.setStatus(SmsMsgStatusEnum.SENDING.index);
            String accessNumber = gateWayMaps.get(gatewayId).getAccessNumber();
            accessNumber += user.getExtendCode();
            accessNumber = accessNumber + entity.getAccessNumber();
            entity.setAccessNumber(accessNumber);
            entity.setGatewayId(Integer.parseInt(gatewayId));
            //MSG表入库队列
            String msgJson = JSON.toJSONString(entity);
            logger.info("handlerIndustry entity json : {}", msgJson);
            JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, msgJson);
            //行业网关发送队列
            String key = String.format(JedisKey.SMS_QUEUE_INDUSTRY_MSG_SEND, gatewayId);
            JedisService.lpush(key, msgJson);
        }
    }

    /**
     * 处理营销短信
     */
    public static void handlerSimpleMarket(Collection<String> phones, SendQueueEntity entity, SmsUser user, Map<String, SmsGateway> gateWayMaps, String gatewayId) {
        List<String> dbList = new ArrayList<>();
        StringBuilder phoneList = new StringBuilder();
        StringBuilder messageIdList = new StringBuilder();
        for (String phone : phones) {
            String[] mate = SmsMateCache.mate(phone);
            if (mate != null) {
                entity.setProvince(mate[0]);
                entity.setCity(mate[1]);
            }
            entity.setMessageId(CommUtil.generateMessageId());
            entity.setPhone(phone);
            entity.setOperator(CommUtil.getPhoneOperator(phone));
            entity.setAction(MessageActionEnum.INSERT.index);
            entity.setNum(CommUtil.splitLongContent(entity.getContent()).size());
            entity.setAccessNumber("0");
            entity.setSendTime(new Date());
            String accessNumber = gateWayMaps.get(gatewayId).getAccessNumber();
            accessNumber += user.getExtendCode();
            accessNumber = accessNumber + entity.getAccessNumber();
            entity.setAccessNumber(accessNumber);
            entity.setGatewayId(Integer.parseInt(gatewayId));
            entity.setStatus(SmsMsgStatusEnum.REQUEST_SUCCESS.index);
            entity.setSendTime(new Date());
            //MSG表入库队列
            String msgJson = JSON.toJSONString(entity);
            dbList.add(msgJson);
            phoneList.append(",").append(phone);
            messageIdList.append(",").append(entity.getMessageId());
        }
        entity.setPhone(phoneList.substring(1, phoneList.length()));
        entity.setMessageId(messageIdList.substring(1, messageIdList.length()));
        String messageInfo = JSON.toJSONString(entity);
        logger.info("handlerSimpleMarket json : {}", messageInfo);
        JedisService.lpush(JedisKey.SMS_QUEUE_MSG_DB, dbList.toArray(new String[dbList.size()]));
        //营销网关发送队列
        String key = String.format(JedisKey.SMS_QUEUE_MARKETING_MSG_SEND, gatewayId);
        JedisService.lpush(key, messageInfo);
    }

//    public static int decide(String customId, int size) {
//        if (StringUtils.isNotBlank(customId)) {
//            Map customs = JSON.parseObject(customId, Map.class);
//            if (size != 0 && customs.get("minCount") != null && size < (Integer) customs.get("minCount")) {
//                return -1;
//            }
//            if (size != 0 && customs.get("maxCount") != null && size > (Integer) customs.get("maxCount")) {
//                return (Integer) customs.get("maxCount");
//            }
//        }
//        return 1;
//    }

    public static Map<String, SmsGateway> getGateWayMaps(String[] dxGateWayIds, String[] ltGateWayIds, String[] ydGateWayIds) {
        Map<String, SmsGateway> smsGatewayHashMap = new HashMap<>();
        Set<String> hashSet = new HashSet<>();
        hashSet.addAll(Arrays.asList(dxGateWayIds));
        hashSet.addAll(Arrays.asList(ltGateWayIds));
        hashSet.addAll(Arrays.asList(ydGateWayIds));
        for (String gateWayId : hashSet) {
            String key = String.format(JedisKey.SMS_GATEWAY, gateWayId);
            SmsGateway smsGateway = JSON.parseObject(JedisService.get(key), SmsGateway.class);
            smsGatewayHashMap.put(gateWayId, smsGateway);
        }
        return smsGatewayHashMap;
    }

    public static String getGatewayId(int operator, String[] ydGateWayIds, String[] ltGateWayIds, String[] dxGateWayIds, SendQueueEntity entity) {
        //行业单个号码网关轮询逻辑
        String account = entity.getAccount();
        String phone = entity.getPhone();
        String gatewayId;
        String key = String.format(JedisKey.SMS_ACCOUNT_PHONE, account, phone);
        String indexStr = JedisService.get(key);
        int index = StringUtils.isBlank(indexStr) ? 0 : Integer.valueOf(indexStr);
        if (operator == SmsMsgOperatorEnum.YD.index) {
            index = ydGateWayIds.length > index ? index : 0;
            gatewayId = ydGateWayIds[index];
            index++;
            index = ydGateWayIds.length > index ? index : 0;
        } else if (operator == SmsMsgOperatorEnum.LT.index) {
            index = ltGateWayIds.length > index ? index : 0;
            gatewayId = ltGateWayIds[index];
            index++;
            index = ltGateWayIds.length > index ? index : 0;
        } else {
            index = dxGateWayIds.length > index ? index : 0;
            gatewayId = dxGateWayIds[index];
            index++;
            index = dxGateWayIds.length > index ? index : 0;
        }
        JedisService.setex(key, Constant.TEN_MINUTES_OF_SECOND / 2, index + "");
        return gatewayId;
    }
}
